﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;

namespace LINQ2Douban
{
    class Program
    {
        static string ConsumerKey = "00c113ee71b2d0b602433bcb55187222";
        static string ConsumerKeySecret = "66433a4a858ddd46";
        static string AccessToken = "d91dbaee1a4ba8278b5930ca4ee2f875";
        static string AccessTokenSecret = "c610083e25e9c077";

        static IDictionary<string, string> ParseResult(string result)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();

            foreach (string s in result.Split('&'))
            {
                if (s.IndexOf("=") > 0)
                {
                    string[] tmp = s.Split('=');
                    parameters.Add(tmp[0], tmp[1]);
                }    
            }

            return parameters;
        }

        static string RequestContent(string url)
        {
            WebClient client = new WebClient();
            client.Credentials = CredentialCache.DefaultCredentials;
            byte[] buffers = client.DownloadData(url);
            string content = Encoding.UTF8.GetString(buffers);
            client.Dispose();

            return content;
        }

        static void Main(string[] args)
        {
            int[] a1 = { 1, 2, 3 };
            int[] a2 = { 4, 5, 6 };
            Enumerables<int> enumerables = new Enumerables<int>();
            enumerables.Add(a1);
            enumerables.Add(a2);

            foreach (var item in enumerables)
            {
                Console.WriteLine(item);
            }
        }

        private static void TestRequest()
        {
            string requestUrl = GenerateUrlWithAuth(
                new Uri("http://api.douban.com/people/@me"),
                "GET",
                ConsumerKey,
                ConsumerKeySecret,
                AccessToken,
                AccessTokenSecret
                );
            Console.WriteLine(requestUrl);
            string content = RequestContent(requestUrl);

            Console.WriteLine(content);
        }

        private static void Test()
        {
            Console.WriteLine("Requesting request token");
            string url = GenerateRequestTokenUrl(ConsumerKey, ConsumerKeySecret);
            string content = RequestContent(url);
            Console.WriteLine(content);
            IDictionary<string, string> results = ParseResult(content);

            foreach (string key in results.Keys)
            {
                Console.WriteLine(
                    "Key: {0}\tValue:{1}", key, results[key]);
            }

            Console.WriteLine("Requesting authorization");
            string authUrl = GenerateAuthorRequestUrl(results["oauth_token"]);
            Console.WriteLine(authUrl);
            Console.Read();

            Console.WriteLine("Requesting access token");
            string accessUrl = GenerateAccessTokenUrl(
                ConsumerKey, ConsumerKeySecret, results["oauth_token"], results["oauth_token_secret"]);
            string accessContent = RequestContent(accessUrl);
            IDictionary<string, string> accessResult = ParseResult(accessContent);

            foreach (string key in accessResult.Keys)
            {
                Console.WriteLine("Key: {0}\tValue:{1}", key, accessResult[key]);
            }
        }

        static void GeneratePostHeader(
            Uri url, string consumerKey, string consumerKeySecret, string accessToken, string accessTokenSecret)
        {
            OAuth.OAuthBase auth = new OAuth.OAuthBase();
            string normalizedUrl = string.Empty;
            string normalizedParameter = string.Empty;
            string timeStamp = auth.GenerateTimeStamp();
            string nonce = auth.GenerateNonce();

            string signature = HttpUtility.UrlEncode(auth.GenerateSignature(
                url,
                consumerKey,
                consumerKeySecret,
                accessToken,
                accessTokenSecret,
                "POST",
                timeStamp,
                nonce,
                OAuth.OAuthBase.SignatureTypes.HMACSHA1,
                out normalizedUrl,
                out normalizedParameter
                ));

            StringBuilder oauthHeader = new StringBuilder();
            oauthHeader.AppendFormat("OAuth realm=\"\", oauth_consumer_key={0}, ", consumerKey);
            oauthHeader.AppendFormat("oauth_nonce={0}, ", nonce);
            oauthHeader.AppendFormat("oauth_timestamp={0}, ", timeStamp);
            oauthHeader.AppendFormat("oauth_signature_method={0}, ", "HMAC-SHA1");
            oauthHeader.AppendFormat("oauth_version={0}, ", "1.0");
            oauthHeader.AppendFormat("oauth_signature={0}, ", signature);
            oauthHeader.AppendFormat("oauth_token={0}", accessToken);

            //构造请求
            StringBuilder requestBody = new StringBuilder("<?xml version='1.0' encoding='UTF-8'?>");
            requestBody.Append("<entry xmlns:ns0=\"http://www.w3.org/2005/Atom\" xmlns:db=\"http://www.douban.com/xmlns/\">");
            requestBody.Append("<content>C# OAuth认证成功</content>");
            requestBody.Append("</entry>");
            Encoding encoding = Encoding.GetEncoding("utf-8");
            byte[] data = encoding.GetBytes(requestBody.ToString());

            // Http Request的设置
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Set("Authorization", oauthHeader.ToString());
            request.ContentType = "application/atom+xml";
            request.Method = "POST";
            request.ContentLength = 0;
            //request.ContentLength = data.Length;
            //Stream requestStream = request.GetRequestStream();
            //requestStream.Write(data, 0, data.Length);
            //requestStream.Close();
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                StreamReader stream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                string responseBody = stream.ReadToEnd();
                stream.Close();
                response.Close();

                Console.WriteLine("发送广播成功");
            }
            catch (WebException e)
            {
                StreamReader stream = new StreamReader(e.Response.GetResponseStream(), System.Text.Encoding.UTF8);
                string responseBody = stream.ReadToEnd();
                stream.Close();

                Console.WriteLine("发送广播失败，原因: " + responseBody);
            }
        }

        static string GenerateUrlWithAuth(
            Uri url, string httpMethod, string consumerKey, string consumerKeySecret, string accessToken, string accessTokenSecret)
        {
            string normalizedUrl = string.Empty;
            string normalizedParameter = string.Empty;

            OAuth.OAuthBase auth = new OAuth.OAuthBase();
            string signature = HttpUtility.UrlEncode(auth.GenerateSignature(
                url,
                consumerKey,
                consumerKeySecret,
                accessToken,
                accessTokenSecret,
                httpMethod,
                auth.GenerateTimeStamp(),
                auth.GenerateNonce(),
                OAuth.OAuthBase.SignatureTypes.HMACSHA1,
                out normalizedUrl,
                out normalizedParameter
                ));

            return string.Format(
                "{0}?{1}&oauth_signature={2}",
                normalizedUrl, normalizedParameter, signature);
        }

        static string GenerateAccessTokenUrl(
            string consumerKey, string consumerKeySecret, string requestToken, string requestTokenSecret)
        {
            Uri url = new Uri("http://www.douban.com/service/auth/access_token");
            string normalizedUrl = string.Empty;
            string normalizedParameter = string.Empty;

            OAuth.OAuthBase auth = new OAuth.OAuthBase();
            string signature = HttpUtility.UrlEncode(auth.GenerateSignature(
                url,
                consumerKey,
                consumerKeySecret,
                requestToken,
                requestTokenSecret,
                "GET",
                auth.GenerateTimeStamp(),
                auth.GenerateNonce(),
                out normalizedUrl,
                out normalizedParameter
                ));

            return string.Format(
                "{0}?{1}&oauth_signature={2}",
                normalizedUrl, normalizedParameter, signature
                );
        }

        static string GenerateAuthorRequestUrl(string token)
        {
            return string.Format("{0}{1}",
                "http://www.douban.com/service/auth/authorize?oauth_token=", token);
        }

        static string GenerateRequestTokenUrl(string consumerKey, string consumerKeySecret)
        {
            OAuth.OAuthBase auth = new OAuth.OAuthBase();
            string normalizedUrl = string.Empty;
            string normalizedParameter = string.Empty;

            string signature = auth.GenerateSignature(
                new Uri("http://www.douban.com/service/auth/request_token"),
                consumerKey,
                consumerKeySecret,
                null,
                null,
                "GET",
                auth.GenerateTimeStamp(),
                auth.GenerateNonce(), 
                out normalizedUrl, 
                out normalizedParameter
                );

            return string.Format("{0}?{1}&oauth_signature={2}",
                normalizedUrl, normalizedParameter, HttpUtility.UrlEncode(signature));
        }
    }
}
